/*
 * @Author: your name
 * @Date: 2021-08-13 10:00:32
 * @LastEditTime: 2021-08-27 17:56:12
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /readbmp/readbitmap.c
 */
#include "./readbitmap.h"
#include "math.h"
#include "defs.h"

int fileType, img_width, img_height;
unsigned int fileSize;
unsigned int pixelPos;
unsigned int bitCount;

char * strcat3(char * p1, char * p2, char * p3){
    char *temp = (char *)malloc(strlen(p1)+strlen(p2)+strlen(p3)+1);
    strcat(temp,p1);
    strcat(temp,p2);
    strcat(temp,p3);

    return temp;
}

char * strcat4(char * p1, char * p2, char * p3, char * p4){
    char *temp = (char *)malloc(strlen(p1)+strlen(p2)+strlen(p3)+strlen(p4)+1);
    strcat(temp,p1);
    strcat(temp,p2);
    strcat(temp,p3);
    strcat(temp,p4);

    return temp;
}

BmpInfo * readBmp(char * path) {
    FILE * bmpfile = fopen(path, "rb");
    if (bmpfile == NULL) oops("can not open file");
    readBmpHeader(bmpfile);
    readBmpInfoHeader(bmpfile);
    if (bitCount == 24) {
        BmpInfo * info = (BmpInfo *) calloc(1, sizeof(BmpInfo));
        uint64_t size = img_height * img_width * 3;
        uint8_t * data = getRgbData(bmpfile);
        info->img_height = img_height;
        info->img_width = img_width;
        info->rgbData = data;
        info->type = 24;
        return info;
    } else if (bitCount == 32) {
        BmpInfo * info = (BmpInfo *) calloc(1, sizeof(BmpInfo));
        uint8_t * data = getRgbaData(bmpfile);
        info->img_height = img_height;
        info->img_width = img_width;
        info->type = 32;
        info->rgbData = data;
        return info;
    }
    fclose(bmpfile);
    return NULL;
}

void readBmpHeader(FILE * bmpfile) {
    unsigned char * p = (unsigned char *) calloc(BIT_HEADER_SIZE, sizeof(unsigned char));
    size_t readsize = fread(p, sizeof(unsigned char), BIT_HEADER_SIZE, bmpfile);
    if (readsize != BIT_HEADER_SIZE) oops("header size error");
    fileType = (p[0] << 8) | p[1];
    fileSize = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2];
    pixelPos = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10];
    // printf("fileType: %x, fileSize: %u, pixelPos: %u\n", fileType, fileSize, pixelPos);
    free(p);
}

void readBmpInfoHeader(FILE * bmpfile) {
    unsigned char * infoSize = (unsigned char *) calloc(BMP_HEADER_SIZE_SIZE, sizeof(unsigned char));
    size_t rs = fread(infoSize, sizeof(unsigned char), BMP_HEADER_SIZE_SIZE, bmpfile);
    if (rs != BMP_HEADER_SIZE_SIZE) oops("info size error");
    int info_size = (infoSize[3] << 24) | (infoSize[2] << 16) | (infoSize[1] << 8) | infoSize[0];
    int remainInfoSize = info_size - BMP_HEADER_SIZE_SIZE;
    unsigned char * info = (unsigned char *) calloc(remainInfoSize, sizeof(unsigned char));
    size_t rsi = fread(info, sizeof(unsigned char), remainInfoSize, bmpfile);
    if (rsi != remainInfoSize) oops("info size error");
    img_width = (info[3] << 24) | (info[2] << 16) | (info[1] << 8) | info[0];
    img_height = (info[7] << 24) | (info[6] << 16) | (info[5] << 8) | info[4];
    bitCount = (info[11] << 8) | info[10];
    int biCompress = (info[15] << 24) | (info[14] << 16) | (info[13] << 8) | info[12];
    int colors = (info[31] << 24) | (info[30] << 16) | (info[29] << 8) | info[28];
    // printf("width: %d, height: %d, bitCount: %d, biCompress: %d, colors: %d\n", img_width, img_height, bitCount, biCompress, colors);
}

uint8_t * getRgbData(FILE * bmpfile) {
    int size = img_width * img_height * 3;
    uint8_t * rgbData = (uint8_t *) calloc(size, sizeof(uint8_t));
    if (rgbData == NULL) oops("malloc failed");
    size_t readsize = fread(rgbData, sizeof(uint8_t), size, bmpfile);
    if (readsize != size) {
        free(rgbData);
        oops("read rgb data failed");
    }
    /*int i;
    for (i = 0; i < size; i += 4) {
        printf("r = %u, g = %u, b = %u\n", rgbData[i], rgbData[i + 1], rgbData[i + 2]);
    }*/

    return rgbData;
}


uint8_t * getRgbaData(FILE * bmpfile) {
    uint32_t size = abs(img_width * img_height * 4);
    uint8_t * data = (uint8_t *) calloc(size, sizeof(uint8_t));
    size_t rd = fread(data, sizeof(uint8_t), size, bmpfile);
    // printf("size = %d\n",size);
    // printf("rd = %d\n",rd);
    if (rd != size) oops("read size error");
    int i;
    /*for (i = 0; i < size; i += 4) {
        printf("r = %u, g = %u, b = %u, a = %u\n", data[i + 2], data[i + 1], data[i], data[i + 3]);
    }*/

    /*FILE * fp = fopen("mydata.csv", "w");
    write_mat(fp, data, size);
    fclose(fp);*/
    
    return data;
}

void write_mat(FILE *fp, uint8_t *m, uint32_t size){

	uint32_t i, j;
	for(i =0; i < size; i+=4){
		fprintf(fp, "\t%u", m[i+2]);
        fprintf(fp, "\t%u", m[i+1]);
        fprintf(fp, "\t%u", m[i]);
        fprintf(fp, "\t%u", m[i+3]);
		 
		fprintf(fp, "\n");
	}
	fprintf(fp, "\n");
}

void write_mat2(FILE *fp, int **m, int N, int M){

	int i, j;
	for(i =0; i< N; i++){
		fprintf(fp, "%d", m[i][0]);
		for(j = 1; j < M; j++){
			fprintf(fp, "\t%d", m[i][j]);
		}   
		fprintf(fp, "\n");
	}
	fprintf(fp, "\n");
}

void write_mat_explain(FILE *fp, char *p){

	fprintf(fp, "%s\n", p);

}

void write_mat_explainbyMBIdx(FILE *fp, int MBdIdx, char *p){

    fprintf(fp, "%s", "索引号为");
    fprintf(fp, "%d", MBdIdx);
    fprintf(fp, "%s", "的");
	fprintf(fp, "%s\n", p);

}

void write_mat_explainfeatures(FILE *fp, int fframe, int listframe, int blocknum, int ffeature1, int ffeature2, int ffeature3,int lfeature1, int lfeature2, int lfeature3){

    fprintf(fp, "%s", "第");fprintf(fp, "%d", fframe);fprintf(fp, "%s", "帧与第");fprintf(fp, "%d", listframe);
    fprintf(fp, "%s", "帧的");fprintf(fp, "%d", blocknum);fprintf(fp, "%s", "序号块相似 第");fprintf(fp, "%d", fframe);
    fprintf(fp, "%s", "帧该块其特征1为");fprintf(fp, "%d ", ffeature1); fprintf(fp, "%s", "特征2为");fprintf(fp, "%d ", ffeature2);
    fprintf(fp, "%s", "第");fprintf(fp, "%d ", listframe);fprintf(fp, "%s", "特征3为");fprintf(fp, "%d ", ffeature3);
    fprintf(fp, "%s", "帧该块其特征1为");fprintf(fp, "%d ", lfeature1); fprintf(fp, "%s", "特征2为");fprintf(fp, "%d ", lfeature2);
    fprintf(fp, "%s", "特征3为");fprintf(fp, "%d\n", lfeature3);
    fprintf(fp, "%s", "该块特征1差值为");fprintf(fp, "%d ", abs(ffeature1-lfeature1)); 
    fprintf(fp, "%s", "该块特征2差值为");fprintf(fp, "%d ", abs(ffeature2-lfeature2)); 
    fprintf(fp, "%s", "该块特征3差值为");fprintf(fp, "%d\n\n", abs(ffeature3-lfeature3)); 

}

void getBlockPosition(int** arr, int x1, int y1, int x2, int y2){
    //int arr[y2-y1+1][2];
    int i;
    int count = y2-y1+1;
    for ( i = 0; i < count; i++)
    {
        arr[i][0] = x1 + IMAGE_WIDTH*y1;
        arr[i][1] = arr[i][0] + x2 - x1;
        y1++;
    }
}

int **calloc_mat_int(int dimX, int dimY){
	int **m = calloc(dimX, sizeof(int*));
	int *p = calloc(dimX*dimY, sizeof(int));
	int i;
	for(i=0; i <dimX;i++){
		m[i] = &p[i*dimY];

	}
	return m;
}

int ***calloc_mat_int3(int dimX, int dimY, int dimZ){
	int ***m = calloc(dimX, sizeof(int**));
	//int *p = calloc(dimX*dimY, sizeof(int));
	int i,j,k;
	for(i=0; i <dimX;i++){
		m[i] = calloc(dimY, sizeof(int*));
        for(j=0; j <dimY;j++){
            m[i][j] = calloc(dimZ, sizeof(int));
            /*for ( k = 0; i < dimZ; k++)
            {
                m[i][j][k] = i+j+k;
            }*/
        }

	}
	return m;
}

uint8_t * getBlockRgbaData(uint8_t * data, int** blockPosition, int*** rgbdata, int row_count) {
    int i, j, len;

    len = blockPosition[0][1] - blockPosition[0][0]+1;
    for ( i = 0; i < row_count; i++)
    {
        for ( j = 0; j < len; j++)
        {
            rgbdata[i][j][0] = data[4*(blockPosition[i][0]+j)+2];
            rgbdata[i][j][1] = data[4*(blockPosition[i][0]+j)+1];
            rgbdata[i][j][2] = data[4*(blockPosition[i][0]+j)];
            rgbdata[i][j][3] = data[4*(blockPosition[i][0]+j)+3];
        }
        
    }

    return data;
}

void getYuvfromRgb(int ***rgbdata, int ***yuvdata, int dx, int dy){
    int i,j,k;
    for (i = 0; i < dy; i++)
    {
        for (j = 0; j < dx; j++)
        {
            yuvdata[i][j][0] = (77*rgbdata[i][j][0] + 150*rgbdata[i][j][1] + 29*rgbdata[i][j][2] + 128) >> 8;
            yuvdata[i][j][1] = ((-44*rgbdata[i][j][0] - 87*rgbdata[i][j][1] + 131*rgbdata[i][j][2] + 128) >> 8) + 128;
            yuvdata[i][j][2] = ((131*rgbdata[i][j][0] - 110*rgbdata[i][j][1] - 21*rgbdata[i][j][2] + 128) >> 8) + 128;
        }
    }
}

/*void putYin64x4x4(int ***yuv_y64x4x4Data, int ***yuvData){
    int i,j,k,index;
    index = -2;
    for ( i = 0; i < block32; i++ )
    {
        if(i%4==0) index++;
        for ( j = 0; j < block32; j++ )
        {
            if(j%4==0) index++;
            yuv_y64x4x4Data[index][i][j] = yuvData[i][j][0];
        }
        
    }
    
}*/

void putYinBlock(int **yuv_yData, int ***yuvData, int dx, int dy){
    int i,j;
    for ( i = 0; i < dy; i++ )
    {
        for ( j = 0; j < dx; j++ )
        {
            yuv_yData[i][j] = yuvData[i][j][0];
        }
    } 
}

void dct(int **DCTMatrix, int **Matrix, int N, int M){

	int i, j, u, v;

	for (u = 0; u < N; ++u) {
		for (v = 0; v < M; ++v) {
            float temp = 0;
			for (i = 0; i < N; i++) {
				for (j = 0; j < M; j++) {
					if(u==0 && v==0){
						temp += (1./block32)*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
                    }
					else if(u==0||v==0){
						temp += (sqrt(2)/block32)*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
                    }
					else
						temp += (2./(block32))*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
						//DCTMatrix[u][v] += (Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
				}               
			}
            DCTMatrix[u][v] = temp;
		}
	}  
}

int ** getdctBloct(int **Matrix, int N, int M){

    int **DCTMatrix = calloc_mat_int(block32,block32);

	int i, j, u, v;

	for (u = 0; u < N; ++u) {
		for (v = 0; v < M; ++v) {
            float temp = 0;
			for (i = 0; i < N; i++) {
				for (j = 0; j < M; j++) {
					if(u==0 && v==0){
						temp += (1./block32)*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
                    }
					else if(u==0||v==0){
						temp += (sqrt(2)/block32)*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
                    }
					else
						temp += (2./(block32))*(Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
						//DCTMatrix[u][v] += (Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
				}               
			}
            DCTMatrix[u][v] = temp;
		}
	}  
    return DCTMatrix;
}

void diff(int **diffMatrix, int **scaleMatrix, int **Matrix, int N, int M){
    int i,j;

    for (i = 0; i < N; i++) {
        scaleMatrix[i][M] = Matrix[i][0];
    }
    for (j = 0; j <M; j++)
    {
        scaleMatrix[N][j] = Matrix[0][j];
    }
    for (i = 0; i < N; i++) {
		for (j = 0; j < M; j++) {
            scaleMatrix[i][j] =  Matrix[i][j];
        }
    }
    
    for (i = 0; i < N; i++) {
		for (j = 0; j < M; j++) {
            diffMatrix[i][j] = 2*scaleMatrix[i][j] - scaleMatrix[i+1][j] - scaleMatrix[i][j+1];
        }
    }

}

//反DCT
void idct(int **Matrix, int **IDCTMatrix, int N, int M){
	int i, j, u, v;

	for (i = 0; i < N; ++i) {
		for (j = 0; j < M; ++j) {
            float temp = 0;
			for (u = 0; u < N; u++) {
				for (v = 0; v < M; v++) {
					if(u==0 && v==0)
						temp += (1./block32)*(Matrix[u][v] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
					else if(u==0||v==0)
						temp += (sqrt(2)/block32)*(Matrix[u][v] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
					else
						temp += (2./(block32))*(Matrix[u][v] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v));
				}               
			}
            IDCTMatrix[i][j] = temp;
		}
	} 
}

//量化
void quant32x32(int **DCTMatrix, int **QuantMatrix, int N, int M){
    int i, j;
    for (i = 0; i < N; i++) {
		for (j = 0; j < M; j++) {
            QuantMatrix[i][j] =  DCTMatrix[i][j]/Qstep;
        }
    }
}

//反量化
void dequant32x32(int **QuantMatrix, int **DquantMatrix, int N, int M){
    int i, j;
    for (i = 0; i < N; i++) {
		for (j = 0; j < M; j++) {
            DquantMatrix[i][j] =  QuantMatrix[i][j]*Qstep;
        }
    }
}

void getYfromyuvDataResidual(int ***yuvDataResidual, int **yuv_yData){
    int i, j;
    for ( i = 0; i < block32; i++){
        for ( j = 0; j < block32; j++){
            yuv_yData[i][j] = yuvDataResidual[i][j][0];
        }
    }
}

void free_mat_int(int **m){
	free(m[0]);
	free(m);
}

void getDiffBetween2Matrix(int **Matrix1, int** Matrix2, int **result){
    int i,j;
    for ( i = 0; i < block32; i++){
        for ( j = 0; j < block32; j++)
        {
            result[i][j] = Matrix1[i][j] - Matrix2[i][j];
        }
        
    }
    
}

//获取选定的某一个区域
void getFullChooseArea(char* path, int ***yuv_yAreaBlockData, int x1, int y1, int x2, int y2){
    int i,j,k;
    BmpInfo *bmp1 = readBmp(path);
    int **BlockPosition1 = calloc_mat_int(DYArea, 2);
    int ***rgbData1 = calloc_mat_int3(DYArea,DXArea,4);
    int ***yuvData1 = calloc_mat_int3(DYArea,DXArea,3);
    int **yuv_yAreaData = calloc_mat_int(DYArea,DXArea);
    //根据左上坐标和右下坐标确定gif位置
    getBlockPosition(BlockPosition1,x1,y1,x2,y2);
    //将gif所有像素点的rgba信息按照从左至右从上至下存储到三维数组rgbData内，前两维表示位置，第三维存储rgba信息
    getBlockRgbaData(bmp1->rgbData, BlockPosition1, rgbData1, DYArea);
    //将rgb信息转换为yuv信息
    getYuvfromRgb(rgbData1, yuvData1,DXArea,DYArea);
    //将Yuv中的Y放置到yuv_yData
    putYinBlock(yuv_yAreaData,yuvData1,DXArea,DYArea);

    //yuv_yAreaBlockData第一维表示块编号，第二、三维是Y分量行列号
    for ( j = 0; j < DYArea; j++)
    {
        for ( k = 0; k < DXArea; k++)
        {
            i = (j/block32)*(DXArea>>5) + k/block32;
            yuv_yAreaBlockData[i][j%block32][k%block32] = yuv_yAreaData[j][k];
        }
    }
    
}

//获取选定的某一个区域
void getFullChooseArea16x16(char* path, int *yuv_yAreaBlockData, int *yuv_uvAreaBlockData, int x1, int y1, int x2, int y2){
    int i,j,k;
    BmpInfo *bmp1 = readBmp(path);
    
    int **BlockPosition1 = calloc_mat_int(16, 2);
    int ***rgbData1 = calloc_mat_int3(16,16,4);
    int ***yuvData1 = calloc_mat_int3(16,16,3);
    int **yuv_yAreaData = calloc_mat_int(16,16);
    //根据左上坐标和右下坐标确定区域位置
    getBlockPosition(BlockPosition1,x1,y1,x2,y2);
    //将gif所有像素点的rgba信息按照从左至右从上至下存储到三维数组rgbData内，前两维表示位置，第三维存储rgba信息
    getBlockRgbaData(bmp1->rgbData, BlockPosition1, rgbData1, 16);
    //将rgb信息转换为yuv信息
    getYuvfromRgb(rgbData1, yuvData1,16,16);
    //将Yuv中的Y放置到yuv_yData
    // putYinBlock(yuv_yAreaData,yuvData1,16,16);

    //yuv_yAreaBlockData第一维表示块编号，第二、三维是Y分量行列号
    i = 0;
    int m = 0;
    for ( j = 0; j < 16; j++)
    {
        for ( k = 0; k < 16; k++)
        {
            yuv_yAreaBlockData[i] = yuvData1[j][k][0];
            ++i;
            if(k%2==0){
                if(j%2==0){
                    yuv_uvAreaBlockData[m] = yuvData1[j][k][1];
                }else if (j%2==1)
                {
                    yuv_uvAreaBlockData[m] = yuvData1[j][k][2];
                }
                ++m;
            }
            
        }
    }

    printf("block块Y分量为：\n");
    for ( i = 0; i < 256; i++)
    {
        if(i%16==0) printf("\n");
        printf("%d\t", yuv_yAreaBlockData[i]);
    }
    printf("\n");
    
    
}

//获取宏块特征
int * getBlock32Features(int **Matrix){

    int * features =  calloc(2,sizeof(int));
    int **dctData = calloc_mat_int(block32,block32);
    dctData = dct32_c(Matrix);
    // dct(dctData, Matrix, block32, block32);
    features[0] = dctData[0][0];
    features[1] = dctData[0][0] + dctData[0][1] + dctData[0][2] + dctData[1][0] + dctData[2][0] + dctData[1][1];
    //printf("%d  %d\n",features[0],features[1]);
    return features;
}

void getBlocklist(int filenum[], link * p[], int frameCount){

    int i,j;
    for ( i = 0; i < AreaBlockCount; i++)
    {
        p[i] = (link *)malloc(sizeof(link));
    }
    
    for ( i = 0; i < frameCount; i++)
    {
        char filenumber[5];
        sprintf(filenumber, "%d", filenum[i]);
        char* path = strcat3("../dump_image/tmpfs/", filenumber, ".bmp");
        //printf("%s\n",path);
        int ***yuv_yAreaBlockData = calloc_mat_int3(AreaBlockCount,block32,block32);
        getFullChooseArea(path, yuv_yAreaBlockData, X1Area, Y1Area, X2Area, Y2Area);
        for ( j = 0; j < AreaBlockCount; j++)
        {
            link * temp = p[j];
            link * a = (link *)malloc(sizeof(link));
            a->block = yuv_yAreaBlockData[j];
            a->dctblock = dct32_c(yuv_yAreaBlockData[j]);
            a->blockNum = j;
            a->blockMedian = findMedian(a->block);
            a->features = getBlock32Features(yuv_yAreaBlockData[j]);
            a->frameNum = filenum[i];
            if(temp->next==NULL) a->next = NULL;
            else a->next = temp->next;
            temp->next=a;
            //temp = temp->next;
        }
        
    }
}

int * generateInitArray(int firstbmp, int lastbmp){
    int i;
    int count = lastbmp - firstbmp + 1;
    int * arr =  calloc(count,sizeof(int));
    for ( i = 0; i < count; i++)
    {
        arr[i] = firstbmp + i;
    }

    return arr;
}

//filenumber 文件名序号
//threshold 阈值
//p[AreaBlockCount] 存储了所有bmp信息的查找链表
void findSimilarBlock(int filenumber, int threshold, link * p[]){
    int * filenum;
    int i;
    //只查找第二十个块
    // int blocknum = 20;
    link * pf[AreaBlockCount];
    for ( i = 0; i < AreaBlockCount; i++)
    {
        pf[i] = (link *)malloc(sizeof(link));
    }
    filenum = generateInitArray(filenumber,filenumber);
    getBlocklist(filenum, pf, 1);

    int * features = calloc(2,sizeof(int));
    // features[0] = pf[blocknum]->features[0];
    // features[1] = pf[blocknum]->features[1];

    FILE * fp = fopen("mydata.csv", "w");
    for ( i = 0; i < AreaBlockCount; i++)
    {
        fprintf(fp,"%d",i);
        write_mat_explain(fp,"块及其DCT为");
        write_mat2(fp, pf[i]->next->block, block32, block32);
        write_mat2(fp, pf[i]->next->dctblock, block32, block32);
    }
    
    // write_mat2(fp, pf[i]->next->block, block32, block32);
    // write_mat2(fp, pf[i]->next->dctblock, block32, block32);
    for ( i = 0; i < AreaBlockCount; i++)
    {
        int * features = calloc(2,sizeof(int));
        features[0] = pf[i]->next->features[0];
        features[1] = pf[i]->next->features[1];
        int pfMedian = pf[i]->next->blockMedian;
        link * x = p[i]->next;
        while (x != NULL)
        {
            if((abs(x->features[0]-features[0])<threshold) && (abs(x->features[1]-features[1]) < threshold && abs(x->blockMedian-pfMedian)<4)){
                // printf("第%d帧与第%d帧的%d序号块相似 ", filenumber, x->frameNum, x->blockNum);
                // printf("第%d帧该块特征1为%d 特征2为%d ", filenumber, features[0], features[1]);
                // printf("第%d帧该块特征1为%d 特征2为%d\n\n", x->frameNum, x->features[0],x->features[1]);
                write_mat_explainfeatures(fp, filenumber, x->frameNum, x->blockNum, features[0], features[1], pfMedian, x->features[0], x->features[1], x->blockMedian);
            }

            x = x->next;

        }
    }

}

void quick_sort( int *a, int n)
{
    int i, j, p, tmp;
    if (n < 2)  return;

    p = a[n / 2]; 

    for ( i = 0, j = n -1;; i++, j--) {
        while (a[i] < p)
            i++;
        while (p < a[j])
            j--;
        if ( i >= j)
            break;
        tmp = a[i]; a[i] = a[j]; a[j] = tmp; 
    }   

    quick_sort( a, i); 
    quick_sort( a + i, n - i); 
}


int findMedian(int **block){
    int i,j;

    int * block1D =  calloc(32*32,sizeof(int));
    for ( i = 0; i < 32; i++)
    {
        for ( j = 0; j < 32; j++)
        {
            block1D[i*32+j] = block[i][j];
        }
    }
    int n = 32*32;
    quick_sort(block1D, n);
    //n为偶数
    int median = (block1D[n/2] + block1D[n/2 + 1])/2;
    //int median = (block1D[n/2] + block1D[n/2 + 1]) >> 1;
    
    return median;
}


/*void free_mat(int *m){
	free(m);
}*/

int read_main(){

    // //定义需要进行残差计算的两帧文件序号
    // int comparefile_num1 = 2272;
    // int comparefile_num2 = 2273;
    // char filenumber1[4];
    // char filenumber2[4];
    // //将整型序号转换为字符串
    // sprintf(filenumber1, "%d", comparefile_num1);
    // sprintf(filenumber2, "%d", comparefile_num2);
    // //字符串拼接形成文件路径
    // char* path1 = strcat3("../dump_image/tmpfs/", filenumber1, ".bmp");
    // char* path2 = strcat3("../dump_image/tmpfs/", filenumber2, ".bmp");

    // ResidualMB* R_array=(int *)calloc(Residual_MB_NUM,sizeof(ResidualMB));
    // //计算得到两帧之间所有残差块，并保存到R_array内
    // R_array = caculatePicResidual(path1, path2, PIC_MB_W, PIC_MB_H);
    // //依据所对比文件序号生成csv文件
    // char * filename = strcat4(filenumber1, "compare", filenumber2, ".csv");
    // int i;
    // FILE * fp = fopen(filename, "w");
    // for ( i = 0; R_array[i].yuvDataResidual!=NULL; i++){
        
    //     int j, k;
    //     printf("保存残差块%d信息到文件%s中\n", R_array[i].MBIdx, filename);
    //     int index = R_array[i].MBIdx;
    //     int **yuv_dctyData = calloc_mat_int(DY,DX);
    //     int **yuv_yData = calloc_mat_int(DY,DX);
    //     int **yuv_quantyData = calloc_mat_int(DY,DX);
    //     int **yuv_dequantyData = calloc_mat_int(DY,DX);
    //     int **yuv_idctyData = calloc_mat_int(DY,DX);
    //     int **yuv_diffyData = calloc_mat_int(DY,DX);
    //     //提取Y分量
    //     getYfromyuvDataResidual(R_array[i].yuvDataResidual, yuv_yData);
    //     //DCT
    //     dct(yuv_dctyData, yuv_yData, block32, block32);
    //     //量化
    //     quant32x32(yuv_dctyData, yuv_quantyData, block32, block32);
    //     //反量化
    //     dequant32x32(yuv_quantyData, yuv_dequantyData, block32, block32);
    //     //反DCT
    //     idct(yuv_dequantyData, yuv_idctyData, block32, block32);
    //     //Y残差分量与经过DCT、量化、反量化、反DCT结果的差值
    //     getDiffBetween2Matrix(yuv_yData, yuv_idctyData, yuv_diffyData);

    //     printf("\n");
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量结果：");
    //     write_mat2(fp, yuv_yData, block32, block32);
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量DCT结果：");
    //     write_mat2(fp, yuv_dctyData, block32, block32);
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量DCT、量化结果：");
    //     write_mat2(fp, yuv_quantyData, block32, block32);
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量DCT、量化、反量化结果：");
    //     write_mat2(fp, yuv_dequantyData, block32, block32);
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量DCT、量化、反量化、反DCT结果：");
    //     write_mat2(fp, yuv_idctyData, block32, block32);
    //     write_mat_explainbyMBIdx(fp, index,"32x32块的Y残差分量与经过DCT、量化、反量化、反DCT结果的差值：");
    //     write_mat2(fp, yuv_diffyData, block32, block32);
    //     free_mat_int(yuv_dctyData);
    //     free_mat_int(yuv_yData);
    //     free_mat_int(yuv_quantyData);
    //     free_mat_int(yuv_dequantyData);
    //     free_mat_int(yuv_idctyData);
    //     free_mat_int(yuv_diffyData);
    // }
    // fclose(fp);
    






    //以2473为t时刻，包含的图片有2468、2469、2470、2471、2472、2473、2474、2475、2476、2477、2478、2560、2704
    //int filenum[] = {2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2560,2704};
    int firstbmp = 2500;
    int lastbmp = 2800;
    int frameCount = lastbmp - firstbmp + 1;
    int * filenum;
    filenum = generateInitArray(firstbmp,lastbmp);
    int i,j,k;
    /*for ( i = 0; i < sizeof(filenum)/sizeof(filenum[0]); i++)
    {
        char filenumber[5];
        sprintf(filenumber, "%d", filenum[i]);
        char* path1 = strcat3("../dump_image/tmpfs/", filenumber, ".bmp");
        BmpInfo *bmp1 = readBmp(path1);
    }*/
    int filenumb = 2468;
    char *filenumber;
    sprintf(filenumber, "%d", filenumb);
    char* path = strcat3("../dump_image/tmpfs/", filenumber, ".bmp");

    //char* path = "../dump_image/tmpfs/2490.bmp"; 
    //FILE * fp = fopen("mydata.csv", "w");
    BmpInfo *bmp = readBmp(path);

    //坐上(453,211),右下(650,342)
    //BlockPosition存放所测试的Block的逐行左端点、右端点像素点位置信息
    //int **yuv_yAreaData = calloc_mat_int(DYArea,DXArea);
    //printf("%d", AreaBlockCount);
    int ***yuv_yAreaBlockData = calloc_mat_int3(AreaBlockCount,block32,block32);
    int **BlockPosition = calloc_mat_int(DY, 2);
    int ***rgbData = calloc_mat_int3(DY,DX,4);
    int ***yuvData = calloc_mat_int3(DY,DX,3);
    int **yuv_yData = calloc_mat_int(DY,DX);
    int **yuv_dctyData = calloc_mat_int(DY,DX);
    int **yuv_diffyData = calloc_mat_int(DY,DX);
    int **yuv_scaleyData = calloc_mat_int(DY+1,DX+1);
    int **yuv_dctdiffyData = calloc_mat_int(DY,DX);
    int **yuv_quantyData = calloc_mat_int(DY,DX);
    int **yuv_dequantyData = calloc_mat_int(DY,DX);
    int **yuv_idctyData = calloc_mat_int(DY,DX);
    
    // //根据左上坐标和右下坐标确定gif位置
    // getBlockPosition(BlockPosition,X1,Y1,X2,Y2);
    // //将gif所有像素点的rgba信息按照从左至右从上至下存储到三维数组rgbData内，前两维表示位置，第三维存储rgba信息
    // getBlockRgbaData(bmp->rgbData, BlockPosition, rgbData, DY);
    // //将rgb信息转换为yuv信息
    // getYuvfromRgb(rgbData, yuvData,DX,DY);
    // //将Yuv中的Y放置到yuv_yData
    // putYinBlock(yuv_yData,yuvData,DX,DY);
    // //对Y分量做差分，如a11 = a11-a12 + a11-a21
    // diff(yuv_diffyData, yuv_scaleyData, yuv_yData, block32, block32);
    // //暂时还不清楚32x32整数变换，对Y分量采用浮点dct计算
    // dct(yuv_dctyData, yuv_yData, block32, block32);
    // //对Y差分值采用浮点dct计算
    // dct(yuv_dctdiffyData, yuv_diffyData, block32, block32);
    // //对Y分量dct结果进行量化
    // quant32x32(yuv_dctyData, yuv_quantyData, block32, block32);
    // //对量化结果反量化
    // dequant32x32(yuv_quantyData, yuv_dequantyData, block32, block32);
    // //对反量化结果执行反DCT
    // idct(yuv_dequantyData, yuv_idctyData, block32, block32);

    link * p[AreaBlockCount];// = (link *)malloc(AreaBlockCount*sizeof(link));
    //link * temp[AreaBlockCount];

    //获取指定区域的所有像素点Y分量信息
    //getFullChooseArea(path, yuv_yAreaBlockData, X1Area, Y1Area, X2Area, Y2Area);

    getBlocklist(filenum, p, frameCount);
    findSimilarBlock(2801, 150, p);
    /*for ( i = 0; i < AreaBlockCount; i++)
    {
        p[i] = (link *)malloc(sizeof(link));
        link * temp = p[i];
        link * a = (link *)malloc(sizeof(link));
        a->block = yuv_yAreaBlockData[i];
        a->dctblock = getdctBloct(yuv_yAreaBlockData[i],block32,block32);
        a->blockNum = i;
        //printf("blocknumber是%d\n",a->blockNum);
        a->features = getBlock32Features(yuv_yAreaBlockData[i]);
        a->frameNum = filenumb;
        a->next = NULL;
        temp->next=a;
        temp = temp->next;

    }*/

    // printf("%d\n",p[1]->next->block[0][5]);

    // printf("p[1].next addr %p\n",p[1]->next);
    // printf("%d\n",p[1]->next->block[0][5]);
    // printf("features0是%d  features是%d\n",p[1]->next->features[0],p[1]->next->features[1]);

    //if(p[0]->next->next == NULL) printf("NULL");

    // link * x = p[8]->next;

    // printf("特征1是%d，特征2是%d\n",x->features[0],x->features[1]);
    // printf("x addr %p  p[1].next addr %p\n",x,p[1]->next);
    // printf("features0是%d  features是%d\n",p[1]->next->features[0],p[1]->next->features[1]);

    // x = x->next;
    // if(x == NULL) printf("NULL");


    //所有结果写进csv表里
    // FILE * fp = fopen("mydata.csv", "w");
    // for ( i = 0; i < AreaBlockCount; i++)
    // {
    //     link * x = p[i]->next;
    //     while (x != NULL)
    //     {
    //         // fprintf(fp, "%d ", x->blockNum);
    //         // fprintf(fp, "%d ", x->frameNum);
    //         // fprintf(fp, "%d %d\n", x->features[0],x->features[1]);
    //         fprintf(fp, "当前块号为%d ", x->blockNum);
    //         fprintf(fp, "当前帧号为%d ", x->frameNum);
    //         fprintf(fp, "当前块特征1为%d 特征2为%d 特征3为%d\n", x->features[0],x->features[1],x->blockMedian);
    //         write_mat2(fp, x->block, block32, block32);
    //         write_mat2(fp, x->dctblock, block32, block32);

    //         x = x->next;

    //     }
    // }
    // fclose(fp);





    // while (x != NULL)
    // {
    //     for ( j = 0; j < block32; j++)
    //     {
    //         for ( k = 0; k < block32; k++)
    //         {
    //             printf("\t%d",x->block[j][k]);
    //         }
    //         printf("\n");
    //     }
    //     printf("\n");

    //     for ( j = 0; j < block32; j++)
    //     {
    //         for ( k = 0; k < block32; k++)
    //         {
    //             printf("\t%d",x->dctblock[j][k]);
    //         }
    //         printf("\n");
    //     }
    //     printf("\n");
    //     printf("帧号是%d\n",x->frameNum);
    //     printf("块号是%d\n",x->blockNum);
    //     printf("特征1是%d，特征2是%d\n",x->features[0],x->features[1]);
    //     printf("中位数是%d\n",x->blockMedian);

    //     x = x->next;

    // }
    

    // for ( i = 0; i < AreaBlockCount; i++)
    // {
    //     for ( j = 0; j < block32; j++)
    //     {
    //         for ( k = 0; k < block32; k++)
    //         {
    //         printf("\t%d",yuv_yAreaBlockData[i][j][k]);
    //         }
    //         printf("\n");
    //     }
    //     printf("\n");
        
    // }

    

    // FILE * fp = fopen("mydata.csv", "w");
    // write_mat_explain(fp,"32x32块的Y分量结果：");
    // write_mat2(fp, yuv_yData, block32, block32);
    // write_mat_explain(fp,"32x32块的Y分量DCT结果：");
    // write_mat2(fp, yuv_dctyData, block32, block32);
    // //write_mat_explain(fp,"32x32块的Y残差分量结果：");
    // //write_mat2(fp, yuv_diffyData, block32, block32);
    // //write_mat_explain(fp,"32x32块的Y残差分量DCT结果：");
    // //write_mat2(fp, yuv_dctdiffyData, block32, block32);
    // write_mat_explain(fp,"32x32块的Y分量DCT、量化结果：");
    // write_mat2(fp, yuv_quantyData, block32, block32);
    // write_mat_explain(fp,"32x32块的Y分量DCT、量化、反量化结果：");
    // write_mat2(fp, yuv_dequantyData, block32, block32);
    // write_mat_explain(fp,"32x32块的Y分量DCT、量化、反量化、反DCT结果：");
    // write_mat2(fp, yuv_idctyData, block32, block32);
    // fclose(fp);
    
    printf("\n");
    

    
}
